package com.ruoyi.base.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.base.domain.SSerial;
import com.ruoyi.base.mapper.SSerialMapper;
import com.ruoyi.base.service.ISSerialService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Transactional(rollbackFor = Exception.class)
public class SSerialServiceImpl extends ServiceImpl<SSerialMapper, SSerial> implements ISSerialService {


    @Override
    public List<SSerial> selectSSerialList(SSerial serial) {
        return baseMapper.selectSSerialList(serial);
    }

    @Override
    public R insertSSerial(SSerial sSerial) throws Exception {
        QueryWrapper<SSerial> queryWrapper = new QueryWrapper<>();

        queryWrapper.lambda()
                .eq(SSerial::getModuleCode,sSerial.getModuleCode());

        if(StringUtils.isNotEmpty(sSerial.getCompanyCod())){
            queryWrapper.lambda()
                    .eq(SSerial::getCompanyCod,sSerial.getCompanyCod());
        }

        if(StringUtils.isNotNull(sSerial.getContractYear())){
            queryWrapper.lambda()
                    .eq(SSerial::getContractYear,sSerial.getContractYear());
        }

        if(StringUtils.isEmpty(sSerial.getContractSpType())){
            sSerial.setContractSpType("1");
        }

        queryWrapper.lambda().eq(SSerial::getContractSpType,sSerial.getContractSpType());

        SSerial checkCode = super.getOne(queryWrapper);

        if(StringUtils.isNotNull(checkCode)){
            return R.fail("存在相同的流水号代码/(部门)/(合同年份)");
        }

        QueryWrapper<SSerial> checkPreQuery = new QueryWrapper<>();

        checkPreQuery.lambda()
                .eq(SSerial::getPreWord,sSerial.getPreWord());

        if(StringUtils.isNotNull(sSerial.getContractYear())){
            checkPreQuery.lambda()
                    .eq(SSerial::getContractYear,sSerial.getContractYear());
        }


        SSerial checkPre = super.getOne(
                checkPreQuery
        );

        if(!("CONTRACT_CODE".equals(sSerial.getModuleCode())||"contract_code".equals(sSerial.getModuleCode()))){
            if(StringUtils.isNotNull(checkPre)){
                return R.fail("存在相同的流水号前缀");
            }
        }


        if("CONTRACT_CODE".equals(sSerial.getModuleCode())){
            //合同编号默认不清空
            sSerial.setIsMonth("N");
            sSerial.setIsYear("N");
        }

        if(!super.save(sSerial)){
            throw new Exception("新增流水号失败");
        }

        return R.ok();
    }

    @Override
    public AjaxResult updateSSerial(SSerial sSerial) {
        System.out.println(sSerial);

        if(StringUtils.isNotEmpty(sSerial.getCompanyCod())){

            QueryWrapper<SSerial> queryWrapper = new QueryWrapper<>();

            queryWrapper.lambda()
                    .eq(SSerial::getModuleCode,sSerial.getModuleCode())
                    .eq(SSerial::getCompanyCod,sSerial.getCompanyCod())
                    .eq(SSerial::getContractSpType,sSerial.getContractSpType())
                    .ne(SSerial::getId,sSerial.getId());

            SSerial checkCode = super.getOne(
                    queryWrapper
            );

            if(StringUtils.isNotNull(checkCode)){
                return AjaxResult.error("存在相同的流水号代码和部门");
            }

        }

        SSerial checkPre = super.getOne(
                new QueryWrapper<SSerial>().lambda()
                        .eq(SSerial::getPreWord,sSerial.getPreWord())
                        .ne(SSerial::getId,sSerial.getId())
        );

        if(StringUtils.isNotNull(checkPre)){
            return AjaxResult.error("存在相同的流水号前缀");
        }

        return super.updateById(sSerial)?AjaxResult.success():AjaxResult.error();
    }

    @Override
    public synchronized int getSerialByCode(String code) {
        int num=0;
        SSerial sSerial = new SSerial();
        QueryWrapper<SSerial> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(SSerial::getModuleCode,code)
                .isNull(SSerial::getCompanyCod);
        sSerial = super.getOne(queryWrapper);
        if(StringUtils.isNotNull(sSerial)) {
            num = sSerial.getCurrentNum();
            sSerial.setCurrentNum(num+1);

            if(!super.updateById(sSerial)){
                return getSerialByCode(code);
            }

        }
        return num;
    }

    @Override
    public synchronized String getSerialNumberByCodeDept(String code, String deptId){
        String serival = "";
        QueryWrapper<SSerial> queryWrapper = new QueryWrapper<>();
        int num = getSerialByCodeDept(code,deptId);
        queryWrapper.lambda().eq(SSerial::getModuleCode,code).eq(SSerial::getCompanyCod,deptId);
        SSerial sSerial =super.getOne(queryWrapper);
        if(StringUtils.isNotNull(sSerial)){

            String time  = "";

            if(StringUtils.isNotEmpty(sSerial.getTimeFormat())){
                SimpleDateFormat sdf = new SimpleDateFormat(sSerial.getTimeFormat());
                time = sdf.format(new Date());
            }

            String strformat = "%0"+sSerial.getSufNum()+"d";
            String number = String.format(strformat,num);
            serival = sSerial.getPreWord()+time+number;
            if(StringUtils.isNotEmpty(sSerial.getSufWord())){
                serival = serival+sSerial.getSufWord();
            }
        }
        return serival;
    }

    private synchronized int getSerialByCodeDept(String code, String deptId) {

        int num=0;
        SSerial sSerial = new SSerial();
        QueryWrapper<SSerial> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(SSerial::getModuleCode,code)
//                .eq(SSerial::getContractSpType,spType)
                .eq(SSerial::getCompanyCod,deptId);
        sSerial = super.getOne(queryWrapper);
        if(StringUtils.isNotNull(sSerial)) {

            num = sSerial.getCurrentNum();

            sSerial.setCurrentNum(num+1);

            if(!super.updateById(sSerial)){
                return getSerialByCodeDept(code,deptId);
            }

        }
        return num;

    }

    @Override
    public synchronized String getSerialNumberByCode(String code) {
        String serival = "";
        QueryWrapper<SSerial> queryWrapper = new QueryWrapper<>();
        int num = getSerialByCode(code);
        queryWrapper.lambda().eq(SSerial::getModuleCode,code);
        SSerial sSerial =super.getOne(queryWrapper);
        if(StringUtils.isNotNull(sSerial)){
            SimpleDateFormat sdf = new SimpleDateFormat(sSerial.getTimeFormat());
            String time = sdf.format(new Date());
            String strformat = "%0"+sSerial.getSufNum()+"d";
            String number = String.format(strformat,num);
            serival = sSerial.getPreWord()+time+number;
            if(StringUtils.isNotEmpty(sSerial.getSufWord())){
                serival = serival+sSerial.getSufWord();
            }
        }
        return serival;
    }

    @Override
    public synchronized String getSerialNumberByCodeDeptYearType(String code,String deptId,Long year,String spType) throws Exception {
        String serival = "";
        QueryWrapper<SSerial> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(SSerial::getModuleCode,code)
                .eq(SSerial::getCompanyCod,deptId)
                .eq(SSerial::getContractYear,year)
                .eq(SSerial::getContractSpType,spType);

        int num = getSerialByCodeDeptYearType(code,deptId,year,spType);

        SSerial sSerial =super.getOne(queryWrapper);
        if(StringUtils.isNotNull(sSerial)){

            String time = year.toString();
            String strformat = "%0"+sSerial.getSufNum()+"d";
            String number = String.format(strformat,num);
            serival = sSerial.getPreWord()+time+number;
            if(StringUtils.isNotEmpty(sSerial.getSufWord())){
                serival = serival+sSerial.getSufWord();
            }
        }
        return serival;
    }

    private synchronized int getSerialByCodeDeptYearType(String code, String deptId, Long year, String spType) throws Exception {

        int num=0;
        QueryWrapper<SSerial> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(SSerial::getModuleCode,code)
                .eq(SSerial::getCompanyCod,deptId)
                .eq(SSerial::getContractYear,year)
                .eq(SSerial::getContractSpType,spType);
        SSerial sSerial = super.getOne(queryWrapper);
        if(StringUtils.isNotNull(sSerial)) {
            num = sSerial.getCurrentNum();
            sSerial.setCurrentNum(num+1);

            if(!super.updateById(sSerial)){
                return getSerialByCodeDeptYearType(code,deptId,year,spType);
            }

        }else {

            //新增一个,如果年份小于最大,则创建当年的 否则年份+1,
            List<SSerial> list = super.list(
                    new QueryWrapper<SSerial>().lambda()
                            .eq(SSerial::getModuleCode,code)
                            .eq(SSerial::getCompanyCod,deptId)
                            .eq(SSerial::getContractSpType,spType)
                            .orderByDesc(SSerial::getContractYear)
            );

            System.out.println("============");
            System.out.println(list);

            if(list.size()>0){


                SSerial maxSerial = list.get(0);

                SSerial newSerial = new SSerial(maxSerial);

//                if(contractYear<maxSerial.getContractYear()||contractYear>maxSerial.getContractYear()+1){
//                    newSerial.setContractYear(contractYear);
//                }else {
//                    newSerial.setContractYear(maxSerial.getContractYear()+1);
//                }

                //选啥年份就插入啥年份的流水号

                newSerial.setContractYear(year);

                System.out.println(newSerial);

                R result = insertSSerial(newSerial);

                if(result.getCode()==200){
                    return getSerialByCodeDeptYearType(code,deptId,year,spType);
                }

            }

        }
        return num;

    }

    @Override
    public synchronized String getSerialNumberByCodeDeptYear(String code, String deptId, Long contractYear) throws Exception {
        String serival = "";
        QueryWrapper<SSerial> queryWrapper = new QueryWrapper<>();
        int num = getSerialByCodeDeptYear(code,deptId,contractYear);
        queryWrapper.lambda()
                .eq(SSerial::getModuleCode,code)
                .eq(SSerial::getCompanyCod,deptId)
                .eq(SSerial::getContractYear,contractYear);
        SSerial sSerial =super.getOne(queryWrapper);
        if(StringUtils.isNotNull(sSerial)){
//            SimpleDateFormat sdf = new SimpleDateFormat(sSerial.getTimeFormat());
            String time = contractYear.toString();
            String strformat = "%0"+sSerial.getSufNum()+"d";
            String number = String.format(strformat,num);
            serival = sSerial.getPreWord()+time+number;
            if(StringUtils.isNotEmpty(sSerial.getSufWord())){
                serival = serival+sSerial.getSufWord();
            }
        }
        return serival;
    }

    private synchronized int getSerialByCodeDeptYear(String code, String deptId, Long contractYear) throws Exception {
        int num=0;
        QueryWrapper<SSerial> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(SSerial::getModuleCode,code)
                .eq(SSerial::getCompanyCod,deptId)
                .eq(SSerial::getContractYear,contractYear);
        SSerial sSerial = super.getOne(queryWrapper);
        if(StringUtils.isNotNull(sSerial)) {
            num = sSerial.getCurrentNum();
            sSerial.setCurrentNum(num+1);

            if(!super.updateById(sSerial)){
                return getSerialByCodeDeptYear(code,deptId,contractYear);
            }

        }else {

            //新增一个,如果年份小于最大,则创建当年的 否则年份+1,
            List<SSerial> list = super.list(
                    new QueryWrapper<SSerial>().lambda()
                            .eq(SSerial::getModuleCode,code)
                            .eq(SSerial::getCompanyCod,deptId)
                            .orderByDesc(SSerial::getContractYear)
            );

            System.out.println("============");
            System.out.println(list);

            if(list.size()>0){


                SSerial maxSerial = list.get(0);

                SSerial newSerial = new SSerial(maxSerial);

//                if(contractYear<maxSerial.getContractYear()||contractYear>maxSerial.getContractYear()+1){
//                    newSerial.setContractYear(contractYear);
//                }else {
//                    newSerial.setContractYear(maxSerial.getContractYear()+1);
//                }

                //选啥年份就插入啥年份的流水号

                newSerial.setContractYear(contractYear);

                System.out.println(newSerial);

                R result = insertSSerial(newSerial);

                if(result.getCode()==200){
                    return getSerialByCodeDeptYear(code,deptId,contractYear);
                }

            }

        }
        return num;
    }

    public Integer getIntegerByObject(Object object){
        Integer in = null;

        if(StringUtils.isNotNull(object)){

            if(object instanceof Integer){
                in = (Integer) object;
            }else if(object instanceof String){
                in = Integer.parseInt((String) object);
            }else if(object instanceof Double){
                in = (int)((double)object);
            }else if(object instanceof Float){
                in = (int)((float)object);
            }else if(object instanceof BigDecimal){
                in = ((BigDecimal)object).intValue();
            }else if(object instanceof Long){
                in = ((Long)object).intValue();
            }

        }
        return in;
    }

    public void updateFailList(List<SSerial> list){

        if(list.size()>0){
            for(SSerial serial:list){

                if(super.updateById(serial)){
                    list.remove(serial);
                }

            }
        }

        if(list.size()>0){
            updateFailList(list);
        }

    }

    @Override
    public void updateSerialCron(String type) {
//        lock.lock();
        List<SSerial> failList = new ArrayList<>();


        if("month".equals(type)){
            List<SSerial> monList = super.list(
                    new QueryWrapper<SSerial>().lambda()
                            .eq(SSerial::getIsMonth,"Y")
            );

            if(monList.size()>0){

                List<SSerial> updateList = new ArrayList<>();

                for(SSerial sSerial:monList){

//                    SSerial update = new SSerial();
//
//                    update.setId(sSerial.getId());
//
//                    update.setCurrentNum(1);
//
//                    update.setUpdateTime(new Date());
                    sSerial.setCurrentNum(1);
                    sSerial.setUpdateTime(new Date());

                    if(!super.updateById(sSerial)){
                        failList.add(sSerial);
                    }
                }

            }
        }else if("year".equals(type)){

            List<SSerial> yearList = super.list(
                    new QueryWrapper<SSerial>().lambda()
                            .eq(SSerial::getIsYear,"Y")
            );

            if(yearList.size()>0){

                List<SSerial> updateList = new ArrayList<>();

                for(SSerial sSerial:yearList){

//                    SSerial update = new SSerial();
//
//                    update.setId(sSerial.getId());
//
//                    update.setCurrentNum(1);
//
//                    update.setUpdateTime(new Date());

                    sSerial.setCurrentNum(1);
                    sSerial.setUpdateTime(new Date());

                    if(!super.updateById(sSerial)){
                        failList.add(sSerial);
                    }
                }

            }
        }else if("daily".equals(type)){
            List<SSerial> dailyList = super.list(new QueryWrapper<SSerial>().lambda().eq(SSerial::getIsDaily,"Y"));

            if(dailyList.size()>0){

                for(SSerial sSerial:dailyList){

                    sSerial.setCurrentNum(1);
                    sSerial.setUpdateTime(new Date());

                    if(!super.updateById(sSerial)){
                        failList.add(sSerial);
                    }
                }

            }

        }

        if(failList.size()>0){
            updateFailList(failList);
        }

    }

}
